home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1998 January: Mac OS SDK / Dev.CD Jan 98 SDK1.toast / Development Kits (Disc 1) / QuickDraw 3D / RAVE SDK 1.5 MacOS / Projects / S3V Docs / Writing Sneak3view Tests < prev   
Encoding:
Text File  |  1997-08-14  |  14.3 KB  |  291 lines  |  [TEXT/CWIE]

  1. Writing Sneak3view Tests
  2. ======= ========== ===== 
  3.  
  4.  
  5. 3/29/96
  6.  
  7.  
  8.  
  9.  
  10.  
  11. Introduction
  12. ============ 
  13.  
  14. This document explains how to create your own tests for Sneak3view.  The 
  15. application itself, which is described in "Sneak3view Documentation," 
  16. comes with a number of built-in tests.  These should be sufficient to begin 
  17. debugging your drawing engine.  Eventually, however, you will want to 
  18. devise your own tests to debug a particular feature of your drawing engine.  
  19.  
  20. The process of writing Sneak3view tests is essentially as follows: write 
  21. some C code to draw something to the screen.  You will probably want to 
  22. mirror the RAVE drawing calls to both draw contexts.  There are libraries 
  23. of functions included with Sneak3view which simplify that task.  Then add 
  24. some code to S3TestRegister.c to register your new test so that it will 
  25. show up in Sneak3view's test menu.  Finally, recompile Sneak3view and run 
  26. your test.  Repeat as necessary.
  27.  
  28.  
  29. Writing Tests
  30. ======= ===== 
  31.  
  32. Although Sneak3view is written in C++ using PowerPlant, the tests 
  33. themselves are written in plain C.  Unless you want to customize a part 
  34. of Sneak3view's interface, there should be no need to delve into the 
  35. PowerPlant code.
  36.  
  37. The files you will need to access in order to write your own tests are 
  38. mostly in just two folders, Interfaces and Tests.  Interfaces contains the 
  39. header files which the test code can include.  The headers used by the rest 
  40. of Sneak3view are in the Headers folder and won't be of much use in 
  41. writing tests.
  42.  
  43. The Tests folder contains the test code itself.  In the Sneak3view 
  44. distribution there are several files in this folder.  Of these, only 
  45. S3TestRegister.c is required.  You do not need to compile the tests in the 
  46. other files into the application, but they are useful examples of how to 
  47. write tests.  Some of the tests in S3MoreTests.c use hard-coded file names, 
  48. so they may or may not work if you try to run them.
  49.  
  50.  
  51. A Basic Example
  52. = ===== ======= 
  53.  
  54. As a simple example of a Sneak3view test, take a look at S3TestTriGouraud, 
  55. in S3RandomTests.c.  The function draws (by default) 100 gouraud-shaded 
  56. triangles in both draw contexts simultaneously.  
  57.  
  58. First notice that every test has a single parameter of type S3tTestInfo*.  
  59. S3tTestInfo is an opaque data type which contains all the values which are 
  60. controlled from the settings window in Sneak3view.  Its fields are 
  61. accessed through the functions in S3TestInfo.h.  The return type of every 
  62. test is S3tTestStatus, which is an enumeration of possible test results: 
  63. failure, success, etc.  If the test returns kS3Status_Failure, an alert to 
  64. that effect is displayed to the user, so it's important to return the 
  65. appropriate value at the end of a test.
  66.  
  67. Only a few lines of code are required in S3TestTriGouraud to draw the 
  68. triangles.  First S3TestInfo_GetArgString is called to get a pointer to the 
  69. string of arguments (if any) the user passed to the test.  The argument 
  70. string is scanned to find an unsigned integer.  If one is found, it becomes 
  71. the number of triangles that this test will draw.  Otherwise, it will draw 
  72. 100 triangles.
  73.  
  74. S3Test_RenderStart is then called to begin rendering.  S3TestSystem.h 
  75. contains the prototypes of functions like S3Test_RenderStart which mirror 
  76. RAVE calls to both draw contexts.  Each of the routines in S3TestSystem.h 
  77. take an S3tTestInfo pointer and possibly one or more other parameters.  In 
  78. the case of S3Test_RenderStart, the function first calls QARenderStart on 
  79. the left draw context and then on the right.
  80.  
  81. Inside the for-loop, S3TestUtil_DrawRandomTriGouraud is called.  This 
  82. utility function is prototyped in S3TestUtil.h.  It simply draws a 
  83. gouraud-shaded triangle made up of three randomly-placed and -colored 
  84. verticies.  To create the verticies it calls S3Testutil_RandomVGouraud.  
  85. Drawing the resulting triangle to both contexts is accomplished through 
  86. S3Test_DrawTriGouraud.  
  87.  
  88. Every 20 triangles, S3Test_Flush is called to force the engines to draw the 
  89. triangles they have accumulated.  After the flush, the function calls 
  90. S3TestInfo_CheckForCancel.  This routine scans the event queue for a
  91. command-period event.  If it finds one it returns true.  This lests the 
  92. user cancel potentially lengthy operations.  Note that if you are trying to 
  93. time your engine's peak drawing speed, you probably don't want to call
  94. S3TestInfo_CheckForCancel inside an inner loop.
  95.  
  96. At the end of the loop, S3Test_RenderEnd is called to finish the rendering 
  97. process.  Finally, status is returned to indicate whether the test was 
  98. successfully completed or was instead cancelled.
  99.  
  100.  
  101. A More Interesting Example
  102. = ==== =========== ======= 
  103.  
  104. S3ShowAllMipMaps is a rather more complex test.  For one thing, it 
  105. retrieves the texture's and the window's height and width from the 
  106. S3tTestInfo, using functions like S3TestInfo_GetTextureWidth.  It then 
  107. makes sure that the window is large enough to contain the triangles the 
  108. test is about to draw.  If the window is too small, the test puts up an 
  109. alert to that effect, letting the user know how big the window must be for 
  110. the test to continue.  
  111.  
  112. S3StopAlert, prototyped in S3Alert.h, is a function which simply displays a 
  113. stop alert box.  You can pass it either a STR# resource ID and index or a 
  114. Pascal string.  S3ShowAllMipMaps builds up the string at runtime.  Since 
  115. the only resource fork open at runtime is Sneak3view's, it is generally 
  116. best to use a Pascal string constant for your alert messages.
  117.  
  118. The function also ensures that the Create Mipmap option has been checked in 
  119. the settings window.  It calls S3TestInfo_GetTextureFlags to retrieve the 
  120. bitmask that Sneak3view passed to QATextureNew when it created the texture.  
  121. If the Create Mipmap option has not been selected, another stop alert is 
  122. displayed.
  123.  
  124. Finally, S3ShowAllMipMaps draws the texture at each of its mipmapped 
  125. sizes.  The texture is rendered onto a square which is made up of two 
  126. triangles using S3Test_DrawTriTexture.
  127.  
  128.  
  129. Timing Drawing Operations
  130. ====== ======= ========== 
  131.  
  132. Most RAVE calls are non-blocking: they return as soon as the geometry, e.g.  
  133. a triangle, has been passed to the engine, but before the engine has drawn 
  134. the triangle.  Thus to get accurate timing information you can't simply 
  135. measure the time between a call to QARenderStart and QARenderEnd.  Instead, 
  136. you must use QASync, which is a RAVE call that blocks until all the 
  137. rendering in a particular context has finished.  So to time the rendering 
  138. of a scene, you could call S3MicrosecondCount (from S3Utilities.h) just 
  139. before S3Test_RenderStart and S3ElapsedMicroseconds just after S3Test_Sync.
  140.  
  141. However, you probably want the time each engine takes to draw its own 
  142. scene, not the total time taken by both engines.  To do this, you must draw 
  143. first in one context and then in the other, using the RAVE calls directly 
  144. (i.e., QADrawTriGouraud() instead of S3Test_DrawTriGouraud).  This is the 
  145. approach S3DrawGouraudTris takes, as shown in S3TimingTests.c.  The 
  146. resulting timing information is printed to the settings window's output 
  147. view.
  148.  
  149.  
  150. Using More Than One Texture
  151. ===== ==== ==== === ======= 
  152.  
  153. Although the Sneak3view settings window lets you select only one texture 
  154. for use in a test, it is possible to load textures from files directly in 
  155. your test code.  The game test, in S3GameTest.c, loads 8 textures and 2 
  156. bitmaps.
  157.  
  158. Rather than hard-coding pathnames to the texture files, it is easier to 
  159. use S3GetNearbyPICT.  In this case, a "nearby" PICT is one whose name 
  160. appears in the Texture and Bitmap popup menus in the settings window.
  161. Given the name of a file, S3GetNearbyPICT returns a PICT handle.  If it 
  162. can find no files with that name, it returns nil.
  163.  
  164. Another way to get a texture is to ask the user for one, with 
  165. S3GetPICTFileSpec.  This routine displays the standard get-file dialog and 
  166. lists only PICT files.  With a valid FSSpec, you can then get a PICT handle 
  167. from S3GetPICTFromFile.
  168.  
  169. Once you have the PicHandle, you can create a new S3Image using 
  170. S3Image_New.  The header S3Image.h contains a C interface to a C++ class 
  171. which handles the storage, mipmapping, etc. of textures and bitmaps.  When 
  172. you create a new S3Image, you must specify whether you want the image to be 
  173. mipmapped and whether all the black pixels should be made transparent.  You 
  174. can either hardcode these flags or else read them from the S3tTestInfo 
  175. struct, using routines like S3TestInfo_GetTextureMakeBlackTransparent.  If 
  176. you do the latter, the user can control whether black should be transparent 
  177. by checking or unchecking that option in the settings window.
  178.  
  179. To create a new texture, you must pass a TQAImage pointer to QATextureNew.  
  180. You can access the TQAImage data in an S3Image by calling 
  181. S3Image_GetImages.  Once you are finished with the image data, after 
  182. calling either QATextureDelete or QATextureDetach (which forces the engine 
  183. to copy the pixmap into its own memory), you must call S3Image_Delete to 
  184. dispose of the off-screen GWorld in which the PICT is stored.
  185.  
  186.  
  187. Calling One Test From Another 
  188. ======= === ==== ==== ======= 
  189.  
  190. One particularly useful feature of Sneak3view is the ability to run a test 
  191. from within another.  As long as the obvious dangers of infinite recursion 
  192. are avoided, this can be extremely useful for regression-testing your 
  193. drawing engine.  By stringing together a number of small tests inside a 
  194. larger one, you can verify your engine's functionality by running a single 
  195. composite test.
  196.  
  197. An example of this is found in S3GameTest.c.  The composite test 
  198. S3GameSceneEveryFormat() runs "Game Scene" over and over, each time 
  199. changing the texture and bitmap formats.  In this way you can check that 
  200. each of the RAVE formats works with your engine in a complex scene.
  201.  
  202. The test first sets a number of fields in the S3tTestInfo structure.  Since 
  203. S3tTestInfo is an opaque data type, you must set the fields through a 
  204. tag-based mechanism, similar to the method used for changing RAVE state 
  205. variables.  For example, the black areas of the bitmaps are forced to be 
  206. transparent with this call:
  207.  
  208.     s3Error = S3TestInfo_SetLong(inTestInfo, 
  209.             kS3TagLong_BitmapMakeBlackTransparent, true);
  210.  
  211. The tags for each of the fields that can be set are listed in S3TestInfo.h.
  212.  
  213. After the initial setup, the test loops through each of the possible 
  214. texture and bitmap formats.  S3TestInfo_SetLong() is used to set the 
  215. formats.  S3TestInfo_RunTest() takes a string and runs the test with that 
  216. name.  
  217.  
  218. When the test has returned, S3GameSceneEveryFormat() calls 
  219. S3TestInfo_AskToContinue().  This routine displays a movable modal dialog 
  220. asking the user to press return to continue the test or click cancel to 
  221. stop it.  That way the user gets a chance to examine the test output 
  222. before moving on to the next test.  Additionally, if the comparison window 
  223. was open when the composite test began, the test output will be compared 
  224. after each test.  While the continue dialog is up, the user can access the 
  225. comparison menu to switch between the various channels.  They can also 
  226. move the comparison window by command-dragging its title bar.  
  227.  
  228. Note that calling a test from inside a composite test does not always 
  229. produce identical behavior to running that same test by clicking the Run 
  230. button in the settings window.  For example, when you click Run, Sneak3view 
  231. creates a new draw context, loads the selected texture and bitmap, if 
  232. necessary, and adds them to each engine.  When the test has completed it 
  233. destroys the draw contexts, textures and bitmaps.
  234.  
  235. On the other hand, calling S3TestInfo_RunTest() does not recreate 
  236. everything in S3tTestInfo.  The test you call will use the same draw 
  237. context as the previous one.  Sometimes this is exactly what you want in 
  238. order to test the behavior of your draw context over time.  In the case of 
  239. the Game Test, this is not a problem since it loads everything it needs and 
  240. then disposes of it all when it's finished.  Be aware, however, that a test 
  241. you call might actually change the state of the S3tTestInfo.  It could, 
  242. for example, delete the textures that were created at the beginning of the 
  243. test.  If the next test that is run depends on those textures, you'll 
  244. encounter problems.  
  245.  
  246. If you do actually want the next test to receive fresh copies of everything 
  247. in S3tTestInfo, call S3TestInfo_Refresh().  This will delete any existing 
  248. draw contexts, textures, etc.  and recreate them based on the current 
  249. values of the S3tTestInfo's fields.  Once again, the state that exists when 
  250. a test is run may not be identical to the state of the settings window.  
  251. Sometimes, of course, this is what you want.  For instance, you could call 
  252. S3OneTexturedRectangle() several times.  In between each repetition, you 
  253. could change the texture FSSpec to point to a different texture and then call 
  254. S3TestInfo_Refresh().  This will provide a different texture to each call 
  255. of S3OneTexturedRectangle().
  256.  
  257.  
  258. Registering a Test
  259. =========== = ==== 
  260.  
  261. Once you have written your test code, you must register it so that it will 
  262. show up in Sneak3view's Test menu.  S3TestRegister.c contains a routine 
  263. called S3Test_Init that gets called when the application starts up.  In 
  264. this function you must call S3Test_Register to register your test.
  265.  
  266. S3Test_Register takes three parameters.  The first is a C string containing 
  267. the name of your test as you want it to appear in the menu.  The second 
  268. parameter is one or more of the values in the S3tTestPrereqs enumeration.  
  269. If your test expects the user to select a texture before it is run, you 
  270. must pass kS3Prereq_Texture.  If you do not, the texture will never be 
  271. created.  kS3Prereq_Bitmap serves a similiar purpose for bitmaps.  If your 
  272. test needs both a texture and a bitmap, pass the sum of these two constants 
  273. in this parameter.  If neither a texture nor a bitmap is required, pass 
  274. kS3Prereq_None.
  275.  
  276. The third parameter is a pointer to your test routine.  If you pass nil 
  277. instead, a divider will be added to the Test menu at that point.  The tests 
  278. appear in the menu in the same order in which you register them.  
  279.  
  280. Rather than registering every test one by one in S3TestRegister.c, it is 
  281. convenient to have one function per source file that in turn registers 
  282. every test in that file.  For instance, S3RandomTests_Register() registers 
  283. all the tests in S3RandomTests.c.  This lets you add tests to a particular 
  284. file without editing S3TestRegister.c.  Note that you will have to 
  285. externally declare any functions you call in S3TestRegister at the top of 
  286. that file.
  287.  
  288. If there is something you need to do when the application is quitting, you 
  289. can put it in S3Test_Exit.
  290.  
  291.